package com.atguigu.gmall.activity.listener;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.util.CacheHelper;
import com.atguigu.gmall.activity.util.DateUtil;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.atguigu.gmall.rabbitmq.config.RabbitConst;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;


import java.util.Date;
import java.util.List;

/**
 * @author: Mamba
 * @version: 1.0
 * @Time: 2021/1/17 20:51
 * @Description:    秒杀监听
 */
@Component
public class SeckillConsumer {

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    //秒杀之监听到MQ中消息
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(value = RabbitConst.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),
                    exchange = @Exchange(value = RabbitConst.EXCHANGE_DIRECT_SECKILL_USER),
                    key = RabbitConst.ROUTING_SECKILL_USER
            )
    })
    public void receiverMessageSeckill(UserRecode userRecode, Message message, Channel channel)throws Exception{
        Long skuId = userRecode.getSkuId();
        String userId = userRecode.getUserId();
        //1.状态位
        Object o = CacheHelper.get(skuId.toString());
        if (!"1".equals(o)){
            System.out.println("此时商品状态位表示无货");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            return;
        }
        //2.校验此用户是否已经买过了  setnx key v  如果存在了 就返回0 false  如果不存在 返回值 1 true
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(RedisConst.SECKILL_USER + userId + ":" + skuId, "V");
        if (!flag){
            System.out.println("此用户已经买过了");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            return;
        }
        //3.校验商品库存
        Object o1 = redisTemplate.opsForList().rightPop(RedisConst.SECKILL_STOCK_PREFIX + skuId);
        if (null == o1){
            System.out.println("已经没有了");
            //没有 更新状态位
            //发消息  skuId:1
            redisTemplate.convertAndSend("seckillpush",skuId + ":0");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            return;

        }
        //有  抢购成功
        redisTemplate.opsForValue().set(RedisConst.SECKILL_ORDERS + userId,skuId.toString());
        //后续其他没写......
        //应答
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }


    @RabbitListener(bindings = {
            @QueueBinding(
                value = @Queue(value = RabbitConst.QUEUE_TASK_1,durable = "true",
                autoDelete = "false"),
                exchange=@Exchange(value = RabbitConst.EXCHANGE_DIRECT_TASK),
                key = RabbitConst.ROUTING_TASK_1
            )
    })
    public void receicerMessage(Message message, Channel channel) throws Exception{

        //将DB中数据压入缓存中
        //1:查询DB中数据  当天数据
        //  -- 当前
        // -- 审核通过的
        // --  还有库存的
        List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(new QueryWrapper<SeckillGoods>()
                .eq("status", 1).gt("stock_count", 0)
                .eq("DATE_FORMAT(start_time,'%Y-%m-%d')",
                        DateUtil.formatDate(new Date())));
        seckillGoodsList.forEach(seckillGoods -> {
            //2:放到缓存中
            if (!redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_GOODS,seckillGoods.getSkuId().toString())){
                //1.秒杀商品压入缓存中
                redisTemplate.opsForHash().put(RedisConst.SECKILL_GOODS,seckillGoods.getSkuId().toString(),seckillGoods);
                //2.使用Redis防止超卖  提前量  将秒杀的商品保存到List类型当中（是商品本身不是数量）  防止超卖
                //List类型  add(123）.add(123） .add(123)  123
                //商品ID
                            Long skuId = seckillGoods.getSkuId();
                //数量
                Integer stockCount = seckillGoods.getStockCount();
                String[] ids = buildSkuStock(skuId.toString(),stockCount);
                redisTemplate.opsForList().leftPushAll(RedisConst.SECKILL_STOCK_PREFIX+skuId,ids);
                //3.状态位
                //发消息  skuId:1
                //信道名字可以随便取
                redisTemplate.convertAndSend("seckillpush",seckillGoods.getSkuId()+":1");
            }
        });
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
    //[123,123,123,...]
    private String[] buildSkuStock(String skuId,Integer stockCount ) {
        String[] ids = new String[stockCount];
        for (int i = 0; i < ids.length; i++) {
            ids[i] = skuId;
        }
        return ids;
    }
}
